/* ------------------------------------------
|	Computers Architecture semester A 2012	|
|				CPU Simulator				|
|No speculation single thread Implementation|			|
|											|
|				presented by:				|
|		Eric Abramov , id: 323541441		|
|		Tal Ben Ari  , id: 032494189		|
---------------------------------------------*/


#include "tomasulo.h"


int freeAllocatedMemory();
int printError(char * msg);
FILE * regs_dump, * mem_dump, * time, * committed, * hitrate, * trace1, * trace2; 
int total_time = 0, cmd_committed = 0;

int main(int argc,char * argv[]) {
	int i;
	char cmd_error[50];

	if (argc != 12) {
		printf("Error: Not enough arguments, right syntax:\n");
		printf("simulator.exe <cmd_file1> <cmd_file2> <config_file> <mem_init> <regs_dump> <mem_dump> <time> <committed> <hitrate> <trace1> <trace2>\n");
		goto EXIT;
	}

	// Opening dump files first:
	
	printf("Opening registers dump file...\n");
	if ((regs_dump = fopen(argv[5],"w")) == NULL) {
		printError("Error opening registers dump file");
		goto EXIT;
	}

	printf("Opening memory dump file...\n");
	if ((mem_dump = fopen(argv[6],"w")) == NULL) {
		printError("Error opening memory dump file");
		goto EXIT;
	}
	
	printf("Opening time file...\n");
	if ((time = fopen(argv[7],"w")) == NULL) {
		printError("Error opening time file");
		goto EXIT;
	}

	printf("Opening committed file...\n");
	if ((committed = fopen(argv[8],"w")) == NULL) {
		printError("Error opening committed file");
		goto EXIT;
	}

	printf("Opening hitrate file...\n");
	if ((hitrate = fopen(argv[9],"w")) == NULL) {
		printError("Error opening hitrate file");
		goto EXIT;
	}

	printf("Opening trace 1 dump file...\n");
	if ((trace1 = fopen(argv[10],"w")) == NULL) {
		printError("Error opening trace 1 dump file");
		goto EXIT;
	}

	printf("Opening trace 2 dump file...\n");
	if ((trace2 = fopen(argv[11],"w")) == NULL) {
		printError("Error opening trace 2 dump file");
		goto EXIT;
	}

	// Loading init files:

	if (loadCmdFile(argv[1]) == -1) {
		printError("Error: invalid 1st cmd file");
		goto EXIT;
	}

	if (parseConfigFile(argv[3]) == -1) {
		printError("Error: invalid config file");
		goto EXIT;
	}

	if (loadMemoryFile(argv[4]) == -1) {
		printError("Error: invalid memory init file");
		goto EXIT;
	}
	
	initializeCaches();
	resetAMAT();
	init_tomasulo();

	// Executing commands from first cmd file:
	printf("Executing commands from first cmd file...\n");
	if (tomasulo(cmd_error, trace1) == -1)
		printError(cmd_error);

	init_commands();

	// Loading second cmd file:
	init_tomasulo();
	if (loadCmdFile(argv[2]) == -1) {
		printError("Error: invalid 2nd cmd file");
		goto EXIT;
	}

	isHalt = 0;
	// Executing commands from second cmd file:

	printf("Executing commands from second cmd file...\n");
	if (tomasulo(cmd_error, trace2) == -1)
		printError(cmd_error);

	// Writing to dump files:
	printf("Writing registers dump file...\n");
	if (printRegisters(regs_dump) == -1) {
		printError("Error writing to registers dump file");
		goto EXIT;
	}

	printf("Writing memory dump file...\n");
	if (printMemory(mem_dump) == -1) {
		printError("Error writing to memory dump file");
		goto EXIT;
	}
	

	printf("Writing time file...\n");
	fprintf(time,"%d",total_time);

	printf("Writing committed file...\n");
	fprintf(committed,"%d",cmd_committed);

	printf("Writing hitrate file...\n");
	printHitRates(hitrate);

	/* Print trace1 and trace2 files
	*/


	printf("Done!");
EXIT:
	freeAllocatedMemory();
	return 0;
}


int printError(char * msg) {
	printf("%s\n",msg);
	if (regs_dump != NULL) fprintf(regs_dump,"%s\n",msg);
	if (mem_dump != NULL) fprintf(mem_dump,"%s\n",msg);
	if (time != NULL) fprintf(time,"%s\n",msg);
	if (committed != NULL) fprintf(committed,"%s\n",msg);
	if (hitrate != NULL) fprintf(hitrate,"%s\n",msg);
	if (trace1 != NULL) fprintf(trace1,"%s\n",msg);
	if (trace2 != NULL) fprintf(trace2,"%s\n",msg);

	return 1;
}

int freeAllocatedMemory() {

	if (commands != NULL) free(commands);
	if (labels != NULL) free(labels);
	if (regs_dump != NULL) fclose(regs_dump);
	if (mem_dump != NULL) fclose(mem_dump);
	if (time != NULL) fclose(time);
	if (committed != NULL) fclose(committed);
	if (hitrate != NULL) fclose(hitrate);
	if (trace1 != NULL) fclose(trace1);
	if (trace2 != NULL) fclose(trace2);

	freeCaches();
	freeTomasulo();

	return 0;
}